<?php
namespace App\Http\Controllers\Api;

use App\Exports\Bureau\UserInfoFillExport;
use App\Http\Controllers\Api\Repositories\WxContRepositories;
use App\Jobs\AttachIpAddressJob;
use App\Lib\WeApp\WeApp;
use App\Models\Bureau\WxBureau;
use App\Models\Bureau\WxBureauCollect;
use App\Models\Bureau\WxBureauComment;
use App\Models\Bureau\WxBureauGroup;
use App\Models\Bureau\WxClub;
use App\Models\Bureau\WxClubFollow;
use App\Models\Bureau\WxClubTeam;
use App\Models\Shop\WxShopOrder;
use App\Models\Shop\WxShopOrderGoods;
use App\Models\User\WxUser;
use App\Models\WxChat;
use App\Wen\Utils\BaiduUtils;
use App\Wen\Utils\BureauUtils;
use App\Wen\Utils\FieldUtils;
use App\Wen\Utils\FileUtils;
use App\Wen\Utils\ImageUtils;
use App\Wen\Utils\Settings;
use App\Wen\Utils\ShopUtils;
use App\Wen\Utils\StrUtils;
use App\Wen\Utils\UserUtils;
use App\Wen\Utils\Utils;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Intervention\Image\Facades\Image;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Maatwebsite\Excel\Facades\Excel;

class BureauController extends BaseController
{
    public function comment_process(Request $request){
        $action = _empty_default_($request->action, '');
        $uid = $request->uid;
        if(_empty_($action)){
            return $this->fail(200001);
        }
        if(!in_array($action, ['add', 'delete'])){
            return $this->fail(200004);
        }
        if(!UserUtils::is_user_can_speak($uid)){
            return $this->fail(200043, [
                'title' => '禁言中，无法言论',
                'content' => '是否前往解除限制',
                'confirmText' => '去解除',
                'target_type' => 6,
                'target_id' => '/pagesA/mine/unlock/unlock?user_id='.$uid
            ], '您当前处于禁言期间，无法言论');
        }

        if($action == 'add'){

            $bureau_id = _empty_default_($request->bureau_id, 0);
            if(_empty_($bureau_id)){
                return $this->fail(200001);
            }

            if(WxBureau::where('id', $bureau_id)->value('status') != 1){
                return $this->fail(200000, [], '该组局活动不是上架中状态');
            }

            if(mb_strlen( str_replace( [Settings::get('default_user_name', '微信用户'), '微信用户', '普通用户'], '', UserUtils::get_cached_user_name($uid) )) != mb_strlen(UserUtils::get_cached_user_name($uid))){
                return $this->fail(200041);
            }

            $comment_id = _empty_default_($request->comment_id, 0);
            if(_empty_($comment_id)){
                $comment_id = 0;
            }

            if($comment_id > 0){
                if(!WxBureauComment::where('id', $comment_id)->where('comment_state', 1)->exists()){
                    return $this->fail(200004, [], '该父级评论不存在');
                }
            }


            $comment_agent_id = _empty_default_($request->comment_agent_id, 0);
            if(_empty_($comment_agent_id)){
                $comment_agent_id = 0;
            }
            if($comment_agent_id > 0){
                $comment_agent_name = UserUtils::get_cached_user($comment_agent_id)['user_name'];
            }

            $comment_content = _empty_default_($request->comment_content, '');
            $comment_img_url = _empty_default_($request->comment_img_url, '');

            if(_empty_($comment_content)){
                return $this->fail(200001);
            }

            $comment_content = strip_tags($comment_content);
            if(mb_strlen($comment_content) <= 0 || mb_strlen($comment_content) > 240){
                return $this->fail(200004, [], '评论内容过长或过短');
            }

            global $__MINI_GLOBAL_IP__;

            // 百度审核
            if(UserUtils::user_permissions_check_by_config($uid, 'audit_bureau_comment_white_list')){
                $need_manual_review = false;
            }else{
                $need_manual_review = true;
                $is_audit_bureau_comment = Settings::get('is_audit_bureau_comment', 0);
                if ($is_audit_bureau_comment == 2) {
                    $filter_result = BaiduUtils::text_filter($comment_content);
                    if($filter_result){
                        if($filter_result['hit_level'] == 2){
                            // 不合规
                            return $this->fail(200016, ['tip'=>$filter_result['tip_list'], 'hit_word'=>$filter_result['hit_word']]);
                        }else if($filter_result['hit_level'] == 0){
                            // 审核通过
                            $need_manual_review = false;
                        }
                    }
                }else if($is_audit_bureau_comment == 0){
                    $need_manual_review = true;
                }else{
                    $need_manual_review = false;
                }
            }

            // 0:审核中，1:审核通过，2:驳回
            $comment_state = 1;
            if($need_manual_review){
                $comment_state = 0;
            }


            $model = new WxBureauComment();
            $model->user_id = $uid;
            $model->bureau_id = $bureau_id;
            if($comment_id > 0){
                $model->comment_id = $comment_id;
            }else{
                $model->comment_id = 0;
            }
            if($comment_agent_id > 0 && $comment_agent_name){
                $model->comment_agent_id = $comment_agent_id;
                $model->comment_agent_name = $comment_agent_name;
            }else{
                $model->comment_agent_id = 0;
            }

            $model->comment_content = $comment_content;
            if(!_empty_($comment_img_url)){
                $model->comment_img_url = $comment_img_url;
            }

            if($__MINI_GLOBAL_IP__){
                $model->ip = $__MINI_GLOBAL_IP__;
            }
            $model->comment_state = $comment_state;
            $r = $model->save();
            if($r){
                Cache::forget('bureau:comment:count:'.$bureau_id);
                return $this->success();
            }
            return $this->fail(200002);
        }else if($action == 'delete'){

        }
    }

    public function detail(Request $request){
        $id = $request->id;
        if(_empty_($id)){
            return $this->fail(200001);
        }

        $bureau = WxBureau::where('id', $id)->first();
        if($bureau){
            BureauUtils::bureau_process($bureau);
            return $this->success($bureau);
        }
        return $this->fail(200003);
    }

    public function comment_list(Request $request){
        $limit = _between_(_empty_default_($request->limit, 10), 1, 100);
        $bureau_id = _empty_default_($request->bureau_id, 0);
        if(_empty_($bureau_id)){
            $this->fail(200001);
        }
        $data = WxBureauComment::where('bureau_id', $bureau_id)->where('comment_id', 0)->where('comment_state', 1)->orderBy('is_sticky', 'desc')->orderBy('id', 'desc')->simplePaginate($limit);
        if($data){
            $data->map(function ($v, $k){
                $v->user = UserUtils::get_cached_user($v->user_id);
                if(_empty_($v->comment_id)){
                    $childData = WxBureauComment::where('comment_id', $v->id)->limit(100)->get();
                    if($childData){
                        $childData->map(function ($v2, $k2){
                            $v2->user = UserUtils::get_cached_user($v2->user_id);
                            $v2->format_time = format_datetime($v2->created_at);
                            return $v2;
                        });
                    }
                    $v->child = $childData;
                }else{
                    $v->child = [];
                }
                $v->format_time = format_datetime($v->created_at);
                return $v;
            });
            return $this->success($data);
        }else{
            return $this->fail(200003);
        }
    }

    public function bureau_list(Request $request) {
        $uid = $request->uid;
        $keyword = $request->keyword;
        $user_id = _empty_default_($request->user_id, 0);
        $collected = _empty_default_($request->collected, 0);
        $club_id = _empty_default_($request->club_id, 0);
        $is_member = _empty_default_($request->is_member, 0);
        $status = _empty_default_($request->status, []);
        $is_master = _empty_default_($request->master, 0);
        $orderBy = _empty_default_($request->orderBy, 'id');
        $order = _empty_default_($request->order, 'desc');
        $classify_id = _empty_default_($request->classify_id, 0);
        $limit = _between_(_empty_default_($request->limit, 10), 1, 100);
        $minprice = _between_(_empty_default_($request->minPrice, 0), 0, 999999999);
        $maxPrice = _between_(_empty_default_($request->maxPrice, 999999999), 0, 999999999);
        $bureau_type = _empty_default_($request->bureau_type, 0);
        $city = _empty_default_($request->city, '');
        if(_empty_($city) || $city == '全国' || $city == '重新定位' || $city == '定位中'){
            $city = '';
        }
        $tag = _empty_default_($request->tag, '');
        if(_empty_($tag) || $tag == '全部'){
            $tag = '';
        }
        if(_empty_($bureau_type)){
            $bureau_type = 0;
        }
        if(!in_array($bureau_type, [0,1,2,3])){
            return $this->fail(200004);
        }
        $time_end_position = _empty_default_($request->time_end_position, 'all');
        if(_empty_($time_end_position)){
            $time_end_position = 'all';
        }
        if(!in_array($time_end_position, ['all', 'before', 'after'])){
            return $this->fail(200004);
        }
        global $__MINI_GLOBAL_TENANT_ID__,$__MINI_GLOBAL_SCENE__;

        if($minprice > $maxPrice){
            return $this->fail(200004);
        }

        if(!in_array($orderBy, ['id', 'distance', 'price', 'created_at', 'state'])){
            return $this->fail(200004);
        }
        if(!in_array($order, ['desc', 'asc'])){
            return $this->fail(200004);
        }
        if($orderBy != 'price'){
            $order = 'desc';
        }
        if(is_string($status)){
            $status = explode(',', $status);
        }
        if(_empty_($status)){
            $status = [1];
        }
        $now = Carbon::now();
        if($orderBy != 'distance'){

            $query = WxBureau::whereIn('status', $status);

            if($is_member == 1){
                $query = $query->whereIn('id', function ($query) use ($uid) {
                    $query->select('bureau_id')
                        ->from('wx_club_team')
                        ->where('members', 'like', "%'".$uid."'%");
                });
            }

            if($collected == 1){
                $query = $query->whereIn('id', function ($query) use ($uid) {
                    $query->select('bureau_id')
                        ->from('wx_bureau_collect')
                        ->where('user_id', $uid)->where('status', 1);
                });
            }

            if($city){
                if(StrUtils::endsWith($city, '市')){
                    $query = $query->where('city', $city);
                }else{
                    $query = $query->where('city', $city.'市');
                }
            }

            if($tag){
                $query = $query->where('tags', $tag);
            }

            if($is_master == 1){
                $query = $query->where('user_id', $uid);
            }

            if($club_id > 0){
                $query = $query->where('club_id', $club_id);
            }

            if($bureau_type > 0){
                $query = $query->where('type', $bureau_type);
            }

            if($time_end_position == 'before'){
                $query = $query->where(function ($query) use ($now) {
                    $query->where('service_date_end', '>', $now->toDateString())
                        ->orWhere(function ($query) use ($now) {
                            $query->where('service_date_end', '=', $now->toDateString())
                                ->where('service_time_end', '>', $now->toTimeString());
                        });
                });
            }else if($time_end_position == 'after'){
                $query = $query->where(function ($query) use ($now) {
                    $query->where('service_date_end', '<', $now->toDateString())
                        ->orWhere(function ($query) use ($now) {
                            $query->where('service_date_end', '=', $now->toDateString())
                                ->where('service_time_end', '<', $now->toTimeString());
                        });
                });
            }

            // 首页
            if($__MINI_GLOBAL_SCENE__ == 147){
                $query = $query->where('exposure_type', 1);
            }else{
                if($__MINI_GLOBAL_SCENE__ == 150){

                }else{
                    $query = $query->where('exposure_type', '<>', 3);
                }
            }

            if($keyword){
                $query = $query->where(function ($query_) use ($keyword) {
                    $query_->orWhere('title', 'like', '%' . $keyword . '%')
                        ->orWhere('intro', 'like', '%' . $keyword . '%');
                });
            }

            if($minprice > 0){
                $query = $query->where('price', '>=', $minprice);
            }
            if($maxPrice != 9999999999){
//                $query = $query->where('price', '<=', $maxPrice);
            }

            if($user_id > 0){
                $query = $query->where('user_id', $user_id);
            }

            if($classify_id > 0){
//                $query = $query->where('classify_id', $classify_id);
            }

            if($orderBy == 'state'){
                $data = $query->orderBy('order', 'desc')->orderByDesc('id')
                    ->paginate($limit);
            }else{
                $data = $query->orderBy('order', 'desc')->orderBy($orderBy, $order)
                    ->paginate($limit);
            }


//            if($classify_id > 0){
//                $query = $query->where('classify_id', $classify_id);
//            }else{
//                $query = $query->whereNotIn('classify_id', $ban_ids);
//            }

            if($data){
                $data->map(function ($v, $k){
                    BureauUtils::bureau_process($v);
                    return $v;
                });
                return $this->success($data);
            }
            return $this->fail(200003);
        }else{
            if($uid > 0){
                $user_ip = WxUser::where('id', $uid)->value('ip');
                global $__MINI_GLOBAL_IP__;
                if($user_ip != $__MINI_GLOBAL_IP__){
                    WxUser::where('id', $uid)->update([
                        'ip' =>  $__MINI_GLOBAL_IP__
                    ]);
                    AttachIpAddressJob::dispatch(2, $uid)->delay(2);
                }
                $user = WxUser::find($uid);
                $longitude = $user->longitude;
                $latitude = $user->latitude;

                if(_empty_($longitude) && _empty_($latitude)){
                    $res = _ip_address($__MINI_GLOBAL_IP__);
                    if(_empty_($res)){
                        return $this->fail(503003);
                    }
                    $longitude = $res['longitude'];
                    $latitude = $res['latitude'];
                }

                $the_base_id = Cache::remember('bureau:goods:new:500', 3600 * 5, function (){
                    $base_id = WxBureau::where('status', 1)->orderBy('order', 'desc')->orderBy('id', 'desc')->skip(500)->value('id');
                    return $base_id > 0 ? $base_id : 0;
                });

                $data = WxBureau::select(DB::raw('*, ( 6378137 * acos( cos( radians('.$latitude.') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('.$longitude.') ) + sin( radians('.$latitude.') ) * sin( radians( latitude ) ) ) ) AS distance'))
                    ->where('id', '>', $the_base_id)
                    ->where('status', 1)
                    ->where('user_id', '<>', $uid)
                    ->having('distance', '<', 300000)
                    ->inRandomOrder()
                    ->simplePaginate(10);
                if($data){
                    $data->map(function ($v, $k){
                        BureauUtils::bureau_process($v);
                        return $v;
                    });
                    return $this->success($data);
                }
            }else{
                return $this->fail(200003, [], '没有获取到您的经纬度信息');
            }
        }
    }

    public function club_info(Request $request) {
        $id = _empty_default_($request->id, 0);
        $uid = $request->uid;

        if (_empty_($id)) {
            if (_empty_($uid)) {
                return $this->fail(200001);
            } else {
                $club = WxClub::where('user_id', $uid)->first();
            }
        } else {
            $club = WxClub::find($id);
        }

        if ($club) {
            BureauUtils::club_procee($club);
            return $this->success($club);
        } else {
            return $this->fail(200003);
        }
    }

    public function bureau_process(Request $request) {
        $type = _empty_default_($request->type, '');
        if ($type == 'club_push') {
            return $this->club_push($request);
        }else if ($type == 'bureau_push') {
            return $this->bureau_push($request);
        }else if ($type == 'bureau_collect') {
            return $this->bureau_collect($request);
        }else if ($type == 'club_follow') {
            return $this->club_follow($request);
        }else if ($type == 'bureau_xlsx') {
            return $this->bureau_xlsx($request);
        }else if ($type == 'bureau_xlsx_table') {
            return $this->bureau_xlsx_table($request);
        }else if ($type == 'bureau_for_update') {
            return $this->bureau_for_update($request);
        }else if ($type == 'bureau_status') {
            return $this->bureau_status($request);
        }else if($type == 'bureau_chat_card'){
            return $this->bureau_chat_card($request);
        }else if($type == 'bureau_sale_reply'){
            return $this->bureau_sale_reply($request);
        }else if($type == 'bureau_share'){
            return $this->bureau_share($request);
        }else if($type == 'bureau_poster'){
            return $this->bureau_poster($request);
        }
    }

    private function bureau_poster(Request &$request){
        $uid = _empty_default_($request->uid, 0);
        $bureau_id_ = _abs(_empty_default_($request->bureau_id, 0));
        global $__MINI_GLOBAL_DEVICE__;
        if(_empty_($bureau_id_)){
            return $this->fail(200001);
        }
        global $__MINI_GLOBAL_PAYCODE_21__,$__MINI_GLOBAL_IS_ADMIN_SUPER__;
        $bureau = WxBureau::find($bureau_id_);
        if(!$bureau){
            return $this->fail(200003);
        }
        BureauUtils::bureau_process($bureau);
        $mini_code = Utils::getMiniCode('/pagesZ/organize-bureau/details/index', 'id='.$bureau->id, $uid);
        if(_empty_($mini_code)){
            return $this->fail(200003);
        }
        $imgurls = [];
        foreach ($bureau->image_urls as $img_obj){
            $imgurls[] = [
                'url' => _array_key($img_obj, 'url', '') . '?imageMogr2/quality/100/format/jpg/interlace/0/crop/277x202/gravity/center/thumbnail/277x'
            ];
        }
        $data = [
            'bg' => Settings::get('app_bureau_poster_bg', 'https://img.mini.minisns.cn/2024/10/19/0/4c3e93059d9907203a8ff7a14e4a4249.png'),
            'code' => $mini_code,
            'title' => StrUtils::limit($bureau->title, 15),
            'service_time_tip' => $bureau->service_time_tip,
            'address_tip' => StrUtils::limit($bureau->address_detailed, 16),
            'image_urls' => $imgurls,
            'club' => $bureau->club
        ];
        if(_empty_($data['image_urls'])){
            return $this->fail(200008);
        }
        return $this->success($data);
    }

    private function bureau_share(Request &$request){
        $uid = _empty_default_($request->uid, 0);
        $bureau_id_ = _abs(_empty_default_($request->bureau_id, 0));
        global $__MINI_GLOBAL_DEVICE__;
        if(_empty_($bureau_id_)){
            return $this->fail(200001);
        }
        global $__MINI_GLOBAL_PAYCODE_21__,$__MINI_GLOBAL_IS_ADMIN_SUPER__;
        $new_app = new WeApp();
        $wxlink = $new_app->getWxLink();
        $bureau = WxBureau::find($bureau_id_);
        if(!$bureau){
            return $this->fail(200003);
        }
        $bureau_user_id = $bureau->user_id;
        $bureau_title = StrUtils::limit($bureau->title);

        $s_content = preg_replace("/<(img|video).*?src[^\'\"]+[\'\"]([^\"\']+)[^>]+>/is", '', $bureau->content);
        $s_content = trim_all_space(strip_tags(html_entity_decode($s_content)), true);

        BureauUtils::bureau_process($bureau);

        $result = [
            'user' => [],
            'url' => '',
            'social' => [

            ],
            'other' => [],
            // 临时加下
            'current_page' => 1
        ];

        if($uid && $uid > 0){
            if($__MINI_GLOBAL_PAYCODE_21__){
                if(!is_mini_examine_mode(11)){
                    $data = DB::table('wx_user')
                        ->whereIn('id', function ($query) use ($uid) {
                            $query->select('object_id')
                                ->from('wx_chat')
                                ->where('user_id', $uid)
                                ->groupBy('object_id')
                                ->orderByDesc('created_at');
                        })->simplePaginate(10, FieldUtils::userInfoColums());
                    if($data->isEmpty()){
                        $data = WxUser::where('is_official', 1)->simplePaginate(10, FieldUtils::userInfoColums());
                    }
                    $result['user'] = $data;
                }
            }

        }

        global $__MINI_GLOBAL_TENANT_ID__;
        if(Settings::get('app_h5_home', '')){
            $result['url'] = Settings::get('app_h5_home', '').'/#/pagesZ/organize-bureau/details/index?id='.$bureau->id . '&fph=1&from_user=' .$uid. '&tenant=' . $__MINI_GLOBAL_TENANT_ID__;
        }else{
            $result['url'] = env('APP_URL');
        }

        $the_only_path = '/pagesZ/organize-bureau/details/index?id=' . $bureau->id. '&fph=1&from_user=' .$uid. '&tenant=' . $__MINI_GLOBAL_TENANT_ID__;

        $share_types = Settings::get('app_bureau_social_share_types', []);
        foreach (['refer', 'wechat', 'timeline', 'qq', 'qzone', 'weibo'] as $key){
            if(!in_array($key, $share_types)){
                continue;
            }
            if($key == 'refer'){
                if($__MINI_GLOBAL_PAYCODE_21__){
                    $result['social'][] = [
                        'action' => 'slider',
                        'color' => Settings::get('--color-primary', '#FC3A72'),
                        'text' => '站内转发',
                        'icon' => 'mini-icon mini-zhanneizhuanfa',
                        'unicode' => 'e699',
                        'target_type' => 6,
                        'target_id' => '/pages/creat/index/creat?bureau_id=' . $bureau->id
                    ];
                }
            }else if($key == 'wechat'){
                $result['social'][] = [
                    'action' => 'wechat',
                    'color' => '#57be6a',
                    'text' => '微信好友',
                    'icon' => 'mini-icon mini-weixin',
                    'unicode' => 'e60b',
                    'share' => json_encode([
                        'provider' => 'weixin',
                        'type' => _empty_(Settings::get('app_meta_appid',  '')) ? 0 : 5,
                        'title' => $bureau_title,
                        'scene' => 'WXSceneSession',
                        'href' => $result['url'],
                        'imageUrl' => $bureau->pic,
                        'miniProgram' => [
                            'id' => Settings::get('app_meta_appid',  ''),
                            'path' => $the_only_path,
                            'type' => 0,
                            'webUrl' => $result['url']
                        ]
                    ]),

                ];
            }else if($key == 'timeline'){
                if($__MINI_GLOBAL_DEVICE__ != 'mp'){
                    $result['social'][] = [
                        'action' => 'timeline',
                        'color' => '#80cc46',
                        'text' => '朋友圈',
                        'icon' => 'mini-icon mini-pengyouquan1',
                        'unicode' => 'e669',
                        'share' => json_encode([
                            'provider' => 'weixin',
                            'type' => 0,
                            'title' => $bureau_title,
                            'summary' => $s_content,
                            'scene' => 'WXSceneTimeline',
                            'href' => $result['url'],
                            'imageUrl' => $bureau->pic,
                            'miniProgram' => [
                                'id' => Settings::get('app_meta_appid',  ''),
                                'path' => $the_only_path,
                                'type' => 0,
                                'webUrl' => $result['url']
                            ]
                        ])
                    ];
                }
            }else if($key == 'qq'){
                if(!_empty_(Settings::get('app_qq_app_appid', ''))){
                    if($__MINI_GLOBAL_DEVICE__ != 'mp') {
                        $result['social'][] = [
                            'action' => 'qq',
                            'color' => '#54b4ef',
                            'text' => 'QQ好友',
                            'icon' => 'mini-icon mini-qq1',
                            'unicode' => 'e66c',
                            'share' => json_encode([
                                'provider' => 'qq',
                                'type' => 1,
                                'title' => $bureau_title,
                                'summary' => $s_content,
                                'href' => $result['url'],
                                'imageUrl' => $bureau->pic
                            ])

                        ];
                    }
                }
            }else if($key == 'qzone'){
                if(!_empty_(Settings::get('app_qq_app_appid', ''))){
                    if($__MINI_GLOBAL_DEVICE__ != 'mp') {
                        $result['social'][] = [
                            'action' => 'qzone',
                            'color' => '#f7cf46',
                            'text' => 'QQ空间',
                            'icon' => 'mini-icon mini-Rrl_s_112',
                            'unicode' => 'e62a',
                            'share' => json_encode([
                                'provider' => 'qq',
                                'type' => 1,
                                'title' => $bureau_title,
                                'href' => $result['url'],
                                'imageUrl' => $bureau->pic
                            ])
                        ];
                    }
                }
            }else if($key == 'weibo'){
                if(!_empty_(Settings::get('app_weibo_app_appid', ''))){
                    if($__MINI_GLOBAL_DEVICE__ != 'mp') {
                        $result['social'][] = [
                            'action' => 'weibo',
                            'color' => '#d4382a',
                            'text' => '微博',
                            'icon' => 'mini-icon mini-weibo',
                            'unicode' => 'e73c',
                            'share' => json_encode([
                                'provider' => 'sinaweibo',
                                'type' => 0,
                                'title' => $bureau_title,
                                'href' => $result['url'],
                                'imageUrl' => $bureau->pic
                            ])

                        ];
                    }
                }
            }
        }

        $system_types = Settings::get('app_bureau_social_system_types', ['showCode', 'edit', 'copyUrl', 'report' ]);
        // promotion
        foreach (['showCode', 'edit', 'copyUrl', 'report'] as $key){
            if(!in_array($key, $system_types)){
                continue;
            }
            if($key == 'showCode'){
                $result['other'][] = [
                    'text' => '生成海报',
                    'icon' => 'mini-icon mini-shengchenghaibao',
                    'action' => 'slider',
                    'unicode' => 'e697',
                    'target_type' => 6,
                    'target_id' => '/pagesZ/organize-bureau/poster/poster?id=' . $bureau->id
                ];
            }else if($key == 'edit'){
                if((is_array($bureau->action_sheets) && in_array('编辑', $bureau->action_sheets)) || $__MINI_GLOBAL_IS_ADMIN_SUPER__){
                    $result['other'][] = [
                        'text' => '编辑',
                        'icon' => 'mini-icon mini-xie',
                        'unicode' => 'e6fd',
                        'action' => 'slider',
                        'target_type' => 6,
                        'target_id' => '/pagesZ/organize-bureau/push/creat?id=' . $bureau->id
                    ];
                }
            }else if($key == 'copyUrl'){
                try {
                    $the_only_path_arr = explode('?', $the_only_path);
                    $url_link = Cache::remember(md5($the_only_path), 3600 * 24, function () use (&$wxlink, &$the_only_path_arr){
                        return $wxlink->genWxUrllink($the_only_path_arr[0] ?? '', $the_only_path_arr[1] ?? '');
                    });
                }catch (\Exception $e){
                    $url_link = $result['url'];
                }

                $bureau_group_text = '';
                foreach ($bureau->groups as $index => $group) {
                    $bureau_group_text = (_empty_default_($group->name, '第'.($index + 1).'组')).'（🎟价格：'.$group->cost_per_person.'元/人）
已上车：'.($group->total_people - $group->member_rest).'/'.$group->total_people.'
报名截止：'.$group->signup_end_time.'

';
                }

                $result['other'][] = [
                    'text' => '复制链接',
                    'icon' => 'mini-icon mini-fuzhilianjie',
                    'unicode' => 'e691',
                    'action' => 'copyUrl',
                    'copy' => '🌟🌟'.$bureau_title.'

⏰活动时间：'.$bureau->service_time_tip.'
📍活动地点：'.$bureau->address_detailed.'('.$bureau->address_name.')
🏁主办俱乐部：'._array_key($bureau->club, 'name', '').'

'.$bureau_group_text.'
- - - - - - - - - - - - - - - - - - - -
🌟报名链接：'.$url_link.'
',
                ];
            }else if($key == 'report'){
                if($bureau_user_id != $uid){
                    $result['other'][] = [
                        'text' => '举报',
                        'icon' => 'mini-icon mini-jubao',
                        'unicode' => 'e694',
                        'action' => 'slider',
                        'target_type' => 6,
                        'target_id' => '/pages/common/report?type=5&object_id=' . $bureau->id
                    ];
                }
            }
        }

//        _logger_(__file__, __line__, $result);
        return $this->success($result);
    }

    private function bureau_sale_reply(Request &$request){
        $reply_type = _empty_default_($request->reply_type, 0);
        if(_empty_($reply_type)){
            return $this->fail(200001);
        }

        $sale_reply = _empty_default_($request->sale_reply, '');
        $sale_reply_img = _empty_default_($request->sale_reply_img, '');

        if($sale_reply_img && strpos($sale_reply_img, 'http') !== 0){
            return $this->fail(200004, [], '图片地址不对');
        }

        $bureau_id = _empty_default_($request->bureau_id, 0);
        $uid = $request->uid;
        if(_empty_($bureau_id)){
            return $this->fail(200001);
        }

        $bureau = WxBureau::find($bureau_id);
        if(!$bureau){
            return $this->fail(200003);
        }
        if($bureau->user_id != $uid && !UserUtils::is_mini_supder_admin($uid)){
            return $this->fail(200000);
        }

        if($reply_type == 1){
            WxBureau::where('id', $bureau->id)->update([
                'pre_sale_reply' => $sale_reply ?? '',
                'pre_sale_reply_img' => $sale_reply_img ?? ''
            ]);
        }else{
            WxBureau::where('id', $bureau->id)->update([
                'after_sale_reply' => $sale_reply ?? '',
                'after_sale_reply_img' => $sale_reply_img ?? ''
            ]);
        }

        Utils::image_state_change([$sale_reply_img]);

        return $this->success();

    }

    private function bureau_chat_card(Request &$request){
        $uid = $request->uid;
        $bureau_id = _empty_default_($request->bureau_id, 0);
        $reply_type = _empty_default_($request->reply_type, 1);
        if(_empty_($bureau_id)){
            return $this->fail(200001);
        }
        $bureau = WxBureau::find($bureau_id);
        if(!$bureau){
            return $this->fail(200003);
        }
        if($bureau->user_id == $uid){
            return $this->fail(200004);
        }
        $card_flag = true;
        $reply_flag = true;
        $msg_reply_flag = true;
        $last_chat = WxChat::where('user_id', $uid)->where('object_id', $bureau->user_id)->orderByDesc('id')->first();
        if($last_chat && $last_chat->expand_type == 7 && $last_chat->expand_id == $bureau->id){
            $card_flag = false;
        }
        DB::beginTransaction();
        try {
            if($card_flag){
                WxContRepositories::add( $uid, $bureau->user_id, '', '', '', 0, 0, 0, 0, 0, 0, $bureau->id);
            }

            // todo:
            if($reply_type == 1){
                if($reply_flag){
                    if($bureau->pre_sale_reply){
                        $chatModel = new WxChat();
                        $chatModel->user_id = $bureau->user_id;
                        $chatModel->object_id = $uid;
                        $chatModel->chat_content = _mini_emoji($bureau->pre_sale_reply);
                        $chatModel->chat_image = '';
                        $chatModel->chat_audio_url = '';
                        $chatModel->chat_audio_length = 0;
                        $chatModel->is_read = 0;
                        $chatModel->chat_state = 0;
                        $chatModel->save();
                    }
                }

                if($msg_reply_flag){
                    if($bureau->pre_sale_reply_img){
                        $chatModel = new WxChat();
                        $chatModel->user_id = $bureau->user_id;
                        $chatModel->object_id = $uid;
                        $chatModel->chat_content = '';
                        $chatModel->chat_image = $bureau->pre_sale_reply_img;
                        $chatModel->chat_audio_url = '';
                        $chatModel->chat_audio_length = 0;
                        $chatModel->is_read = 0;
                        $chatModel->chat_state = 0;
                        $chatModel->save();
                    }
                }
            }else{
                if($reply_flag){
                    if($bureau->pre_sale_reply){
                        $chatModel = new WxChat();
                        $chatModel->user_id = $bureau->user_id;
                        $chatModel->object_id = $uid;
                        $chatModel->chat_content = _mini_emoji($bureau->after_sale_reply);
                        $chatModel->chat_image = '';
                        $chatModel->chat_audio_url = '';
                        $chatModel->chat_audio_length = 0;
                        $chatModel->is_read = 0;
                        $chatModel->chat_state = 0;
                        $chatModel->save();
                    }
                }

                if($msg_reply_flag){
                    if($bureau->after_sale_reply_img){
                        $chatModel = new WxChat();
                        $chatModel->user_id = $bureau->user_id;
                        $chatModel->object_id = $uid;
                        $chatModel->chat_content = '';
                        $chatModel->chat_image = $bureau->after_sale_reply_img;
                        $chatModel->chat_audio_url = '';
                        $chatModel->chat_audio_length = 0;
                        $chatModel->is_read = 0;
                        $chatModel->chat_state = 0;
                        $chatModel->save();
                    }
                }
            }
            DB::commit();
            return $this->success();
        } catch (\Exception $e) {
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            return $this->fail(200002);
        }
    }

    private function bureau_status(Request &$request){
        $status = _empty_default_($request->status, 0);
        $bureau_id = _empty_default_($request->bureau_id, 0);
        $uid = $request->uid;
        if(_empty_($bureau_id)){
            return $this->fail(200001);
        }
        if(!in_array($status, [0, 1, 2, 3])){
            return $this->fail(200001);
        }
        $bureau = WxBureau::find($bureau_id);
        if(!$bureau){
            return $this->fail(200003);
        }
        if($bureau->user_id != $uid && !is_object_user_special($uid, $bureau->tenant_id, true)){
            return $this->fail(200000);
        }
        if($bureau->status === 0){
            if($status == 1){
                if(UserUtils::is_mini_supder_admin($uid)){
                    WxBureau::where('id', $bureau->id)->update([
                        'status' => 1
                    ]);
                    return $this->success();
                }else{
                    return $this->fail(200000);
                }
            }else{
                return $this->fail(200004, [], '活动在审核中');
            }
        }else if($bureau->status === 1){
            if($status == 2 || $status == 3){

                DB::beginTransaction();
                try {
                    // todo:
                    if($bureau->user_id == $uid){
                        WxBureau::where('id', $bureau->id)->update([
                            'status' => 2
                        ]);
                    }else{
                        WxBureau::where('id', $bureau->id)->update([
                            'status' => 3
                        ]);
                    }

                    // 先退款，再通知
                    $order_good_ids = WxShopOrderGoods::where('goods_type', 7)->where('goods_id', $bureau->id)->whereIn('state', [0, 1, 2])->pluck('id')->toArray();
                    if($order_good_ids){
                        foreach ($order_good_ids as $order_good_id){
                            ShopUtils::order_good_refund($order_good_id);
                        }
                        $user_ids = WxShopOrderGoods::whereIn('id', $order_good_ids)->pluck('buyer_user_id')->toArray();
                        if($user_ids){
                            $user_ids = array_unique($user_ids);
                            foreach ($user_ids as $notice_user){
                                UserUtils::add_user_notice(9005, $notice_user,'参加的组局被下架','您参加的组局活动「<a href="/pagesZ/organize-bureau/details/index?id='.$bureau->id.'">'.StrUtils::limit($bureau->title).'</a>」被'.($bureau->user_id == $uid ? '主办方' : '平台管理员').'下架，请注意查收退款',100);
                            }
                        }

                    }

                    DB::commit();
                    return $this->success();
                } catch (\Exception $e) {
                    DB::rollBack();
                    _logger_(__file__, __line__, $e->getMessage());
                }

            }
        }
        return $this->fail(200004);
    }

    private function bureau_xlsx_table(Request &$request){
        $bureau_id = _empty_default_($request->bureau_id, 0);
        if(_empty_($bureau_id)){
            return $this->fail(200001);
        }
        $tables = [];
        $worksheets = [];
        $bureau = WxBureau::find($bureau_id);
        if(!$bureau){
            return $this->fail(200003);
        }

        $headers = [
            [
                'label' => 'UID',
                'key' => 'user_id'
            ],
            [
                'label' => '平台昵称',
                'key' => 'user_name'
            ],
            [
                'label' => '平台头像',
                'key' => 'user_avatar'
            ],
            [
                'label' => '小队',
                'key' => 'team'
            ],
        ];
        $user_info_fill = $bureau->user_info_fill;
        if($user_info_fill && _array_key($user_info_fill, 'data', [])){
            $info_data = _array_key($user_info_fill, 'data', []);
            foreach ($info_data as $key => $item){
                $headers[] = [
                    'label' => $item['name'],
                    'key' => 'key_'.$key
                ];
            }
        }else{
            return $this->fail(200004, [], '该组局没有问卷调查');
        }
        WxBureauGroup::where('bureau_id', $bureau_id)->orderBy('id', 'asc')->get()->map(function ($group, $gindex) use (&$tables, &$worksheets, &$headers){
            $contents = [];
            WxClubTeam::where('group_id', $group->id)->orderBy('id', 'asc')->get()->map(function ($team, $tindex) use (&$group, &$contents, $gindex){
                $members = $team->members;

                $order_id_arr = WxShopOrderGoods::where('goods_type', 7)->where('product_id', $group->id)->whereIn('buyer_user_id', $members)->orderBy(DB::raw('FIND_IN_SET(buyer_user_id, "' . implode(",", $members) . '"' . ")"))->pluck('order_id')->toArray();
                WxShopOrder::where('order_from', 7)->whereIn('id', $order_id_arr)->where('pay_status', 2)->whereIn('status', [0,1,2,3])->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $members) . '"' . ")"))->get(['user_id','order_from', 'user_remark'])->map(function ($order) use ($tindex, &$contents){
                    $user_remark = $order->user_remark;
                    if(is_array($user_remark) && $user_remark){
                        $user = UserUtils::get_cached_user($order->user_id);
                        $info_row_item = [
                            'user_id' => $user['id'].'',
                            'user_name' => $user['user_name'],
                            'user_avatar' => '<img src="'.$user['user_avatar'].'" style="width: 30px; height: 30px;border-radius: 50%;box-shadow: 0px 0px 1px 0px #000000;" />',
                            'team' => '第'.($tindex + 1).'队',
                        ];
                        foreach ($user_remark as $info_index => $info_item){
                            $info_row_item['key_'.$info_index] = $info_item['value'];
                        }
                        $contents[] = $info_row_item;
                    }
                });
            });

            $table = [
                'headers' => $headers,
                'urlCol' => [],
                'contents' => $contents
            ];
            $tables[] = $table;
            $worksheets[] = '第'. ($gindex + 1) .'组';
        });
        return $this->success([
            'tables' => $tables,
            'worksheets' => $worksheets,
            'title' => $bureau->title
        ]);
    }

    private function bureau_xlsx(Request &$request){
        $bureau_id = _empty_default_($request->bureau_id, 0);
        $bureau = WxBureau::find($bureau_id);
        return Excel::download(new UserInfoFillExport($bureau), 'test.xlsx');
    }

    /**
     * 关注店铺
     */
    private function club_follow(Request &$request){
        $club_id = _empty_default_($request->club_id, 0);
        $status = _empty_default_($request->status, 1);
        $uid = $request->uid;

        if(_empty_($club_id)){
            return $this->fail(200001);
        }

        if(!in_array($status, [0, 1])){
            return $this->fail(200004);
        }
        $model = WxClubFollow::where('user_id', $uid)->where('club_id', $club_id)->first();
        if($model){
            if($status == 1){
                if($model->status === 0){
                    $model->status = 1;
                    $model->save();
                }
            }else{
                if($model->status === 1){
                    $model->status = 0;
                    $model->save();
                }
            }
        }else{
            $new_model = new WxClubFollow();
            $new_model->user_id = $uid;
            $new_model->club_id = $club_id;
            $new_model->status = $status;
            $new_model->save();
        }
        return $this->success();
    }

    private function bureau_collect(Request &$request){
        $bureau_id = _empty_default_($request->bureau_id, 0);
        $uid = $request->uid;

        $bureau = WxBureau::find($bureau_id);
        if($bureau){

        }else{
            return $this->fail(200004);
        }

        $model = WxBureauCollect::where('user_id', $uid)->where('bureau_id', $bureau->id)->first();
        if($model){
            if($model->status == 1){
                $model->status = 0;
                $model->save();
            }else{
                $model->status = 1;
                $model->save();
            }
        }else{
            $new_model = new WxBureauCollect();
            $new_model->user_id = $uid;
            $new_model->bureau_id = $bureau_id;
            $new_model->club_id = $bureau->club_id;
            $new_model->status = 1;
            $new_model->save();
        }
        Cache::forget('bureau:collect:count:'.$bureau->id);
        Cache::forget('bureau:avatars:'.$bureau->id);
        return $this->success();
    }

    private function club_push(Request &$request) {
        $uid = $request->uid;
        $id = _empty_default_($request->id, 0);
        $avatar = _empty_default_($request->avatar, '');
        $name = _empty_default_($request->name, '');
        $latitude = _empty_default_($request->latitude, 0);
        $longitude = _empty_default_($request->longitude, 0);
        $address_name = _empty_default_($request->address_name, '');
        $address_detailed = _empty_default_($request->address_detailed, '');
        global $__MINI_GLOBAL_IP__;

        if(_empty_($name) || _empty_($avatar) || _empty_($address_name)){
            return $this->fail(200001);
        }

        $model = WxClub::where('user_id', $uid)->first();
        $id_update_mode = false;
        $old_model_avatar = null;
        $old_model_name = null;
        if ($model) {
            if ($id > 0) {
                if ($model->id == $id) {
                    $id_update_mode = true;
                    $old_model_avatar = $model->avatar;
                    $old_model_name = $model->name;
                } else {
                    return $this->fail(200004);
                }
            }
            if(WxClub::where('name', $name)->where('id', '<>', $model->id)->exists()){
                return $this->fail('俱乐部名称与已有的重复');
            }
        } else {
            $model = new WxClub();
            $model->user_id = $uid;
            if(WxClub::where('name', $name)->exists()){
                return $this->fail('俱乐部名称与已有的重复');
            }
        }

        if (!$model) {
            return $this->fail(200003);
        }

        DB::beginTransaction();
        try {
            $is_need_status_0 = false;
            // todo:
            if($id_update_mode){
                if ($avatar != $old_model_avatar) {
                    $model->avatar_tmp = $avatar;
                    $is_need_status_0 = true;
                }
                if ($name != $old_model_name) {
                    $model->name_tmp = $name;
                    $is_need_status_0 = true;
                }
            }else{
                $model->avatar = $avatar;
                $model->name = $name;
            }

            $model->latitude = $latitude;
            $model->longitude = $longitude;
            $model->address_name = $address_name;
            $model->address_detailed = $address_detailed;
            $model->ip = $__MINI_GLOBAL_IP__;
            if($id_update_mode){
                if($is_need_status_0){
                    $model->status = 0;
                }
            }else{
                $model->status = 0;
            }
            $r = $model->save();
            if ($r) {
                Utils::image_state_change([$avatar]);
                if ($avatar != $old_model_avatar && !$is_need_status_0) {
                    // 删除旧头像
                    FileUtils::force_del_url_file($old_model_avatar);
                }
                if(!$id_update_mode){
                    UserUtils::add_user_experience($model->user_id, 20, 30);
                }
                if(($id_update_mode && $is_need_status_0) || !$id_update_mode){
                    UserUtils::assistant_notice_review(110, $model->id);
                }

                DB::commit();
                Cache::forget('club:info:'.$model->id);
                if ($id > 0) {
                    return $this->success($model->id, 200, '修改成功，管理员审核中');
                } else {
                    return $this->success($model->id, 200, '提交成功，管理员审核中');
                }
            } else {
                DB::rollBack();
                return $this->fail(200002);
            }
        } catch (\Exception $e) {
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            return $this->fail(200002);
        }
    }

    private function bureau_for_update(Request &$request){
        $bureau_id = _empty_default_($request->bureau_id, 0);
        if(_empty_($bureau_id)){
            return $this->fail(200001);
        }
        $bureau = WxBureau::find($bureau_id);
        if(!$bureau){
            return $this->fail(200004);
        }
        $is_for_repeat = _empty_default_($request->is_for_repeat, 0);
        if(_empty_($is_for_repeat)){
            $is_for_repeat = 0;
        }else{
            $is_for_repeat = 1;
        }

        $hours = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
        $minutes = ['00', '05', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55'];

        $startDate = new \DateTime($bureau->service_date_start . ' ' . $bureau->service_time_start);
        $endDate = new \DateTime($bureau->service_date_end . ' ' . $bureau->service_time_end);

        list($start_hour, $start_minute, $start_second) = explode(':', $bureau->service_time_start);
        list($end_hour, $end_minute, $end_second) = explode(':', $bureau->service_time_end);

        $formattedStartDate = $startDate->format('m月d日 D H:i');
        $formattedEndDate = $endDate->format('m月d日 D H:i');

        $baseDate = new \DateTime(WxBureauGroup::where('bureau_id', $bureau->id)->orderBy('id', 'asc')->min('signup_start_time'));
        // 获取当前时间
        $now_date = new \DateTime();
        if ($now_date < $baseDate) {
            $baseDate = $now_date;
        }


        $tagMap = Settings::get('app_bureau_tags', []);

        $exposureMap = [
            1 => '公开（所有地方可见）',
            2 => '私密（不出现在首页）',
            3 => '私密（仅分享链接可见）'
        ];

        $genderMap = [
            0 => '不限制性别',
            1 => '仅男性',
            2 => '仅女性'
        ];

        $refundData = [
            0 => '活动开始前随时可以退款',
            3 => '活动开始前3个小时可以退款',
            12 => '活动开始前12个小时可以退款',
            24 => '活动开始前24个小时可以退款',
            48 => '活动开始前48个小时可以退款',
            72 => '活动开始前3天可以退款',
            168 => '活动开始前7天可以退款',
            240 => '活动开始前10天可以退款',
            255 => '活动不支持无理由退款',
        ];

        $signupScopeMap = [
            1 => '所有人',
            2 => '仅俱乐部成员'
        ];

        $formData = [
            'type' => 'bureau_push',
            'id' => $is_for_repeat ? 0 : $bureau->id,
            'base_date' => $baseDate->format('Y-m-d'),
            'bureau_type' => $bureau->type,
            'title' => $bureau->title,
            'intro' => $bureau->intro,
            'image_urls' => $bureau->image_urls,
            'video_url' => $bureau->video_url,
            'video_cover' => $bureau->video_cover,
            'tags' => [
                'label' => $bureau->tags,
                'value' => array_search($bureau->tags, $tagMap),
                'isDefault' => true
            ],
            'location' => [
                'latitude' => $bureau->latitude,
                'longitude' => $bureau->longitude,
                'address_name' => $bureau->address_name,
                'address_detailed' => $bureau->address_detailed
            ],
            'gameDate' => [
                'label' => $is_for_repeat ? '' : ($formattedStartDate . ' - ' . $formattedEndDate),
                'value' => $is_for_repeat ? ['', ''] : [
                    [($baseDate->diff(new \DateTime(explode(' ', $bureau->service_date_start)[0]))->days) + 1 , array_search($start_hour, $hours), array_search($start_minute, $minutes)],
                    [($baseDate->diff(new \DateTime(explode(' ', $bureau->service_date_end)[0]))->days) + 1, array_search($end_hour, $hours), array_search($end_minute, $minutes)]
                ]
            ],
            'exposure_type' => [
                'label' => $exposureMap[$bureau->exposure_type],
                'value' => $bureau->exposure_type
            ],
            'refund_policy' => [
                'label' => $refundData[$bureau->refund_policy],
                'value' => $bureau->refund_policy
            ],
            'user_info_fill' => $is_for_repeat ? json_encode($bureau->user_info_fill) : '',
            'group' => []
        ];

        $groups = [];
        WxBureauGroup::where('bureau_id', $bureau->id)->orderBy('id', 'asc')->get()->map(function ($item) use (&$groups, &$genderMap, &$signupScopeMap, &$hours, &$minutes, &$baseDate, &$is_for_repeat){
            $signup_end_time = new \DateTime($item->signup_end_time);
            $signup_start_time = new \DateTime($item->signup_start_time);
            list($start_hour, $start_minute, $start_second) = explode(':', explode(' ', $item->signup_start_time)[1]);
            list($end_hour, $end_minute, $end_second) = explode(':', explode(' ', $item->signup_end_time)[1]);

            $start_minute_ = null;
            foreach ($minutes as $minute) {
                if ($minute <= $start_minute) {
                    $start_minute_ = $minute;
                } else {
                    break;
                }
            }

            $group = [
                'id' => $is_for_repeat ? 0 : $item->id,
                'isShowMore' => true,
                'name' => $item->name,
                'total_people' => $item->total_people,
                'cost_per_person' => $item->cost_per_person,
                'is_waiting' => $item->is_waiting,
                'is_limit_one' => $item->is_limit_one,
                'is_real_name' => $item->is_real_name,
                'signup_end_time' => [
                    'label' => $is_for_repeat ? '' : $signup_end_time->format('m月d日 D H:i'),
                    'value' => $is_for_repeat ? '' : [($baseDate->diff(new \DateTime(explode(' ', $item->signup_end_time)[0]))->days) + 1, array_search($end_hour, $hours), array_search($end_minute, $minutes)]
                ],
                'signup_start_time' => [
                    'label' => $is_for_repeat ? '' : $signup_start_time->format('m月d日 D H:i'),
                    'value' => $is_for_repeat ? '' : [$baseDate->diff(new \DateTime(explode(' ', $item->signup_start_time)[0]))->days , array_search($start_hour, $hours), array_search($start_minute_, $minutes)]
                ],
                'signup_scope' => [
                    'label' => $signupScopeMap[$item->signup_scope],
                    'value' => $item->signup_scope
                ],
                'signup_gender' => [
                    'label' => $genderMap[$item->signup_gender],
                    'value' => $item->signup_gender
                ]
            ];
            $groups[] = $group;
        });
        $formData['group'] = $groups;

        return $this->success($formData);
    }

    private function bureau_push(Request &$request) {
        global $__MINI_GLOBAL_PAYCODE_35__,$__MINI_GLOBAL_CURRENT_PLAYER_ID__;
        if(!$__MINI_GLOBAL_PAYCODE_35__){
            return $this->fail(700000);
        }
        $uid = $request->uid;
        $club_id = WxUser::where('id', $uid)->value('club_id');
        global $__MINI_GLOBAL_IP__;
        if(_empty_($club_id)){
            return $this->fail(200043, [
                'title' => '未入驻俱乐部',
                'content' => '请先填写您的俱乐部信息，通过审核后才可发布组局活动',
                'confirmText' => '去填写',
                'target_type' => 6,
                'target_id' => '/pagesZ/organize-bureau/settle-in/index'
            ], '未入驻俱乐部');
        }
        $the_id = _empty_default_($request->id, 0);
        if($the_id > 0){
            $the_update_bureau = WxBureau::find($the_id);
            if(!$the_update_bureau){
                return $this->fail(200000);
            }
            if($the_update_bureau->user_id != $uid && !is_object_user_special($uid, $the_update_bureau->tenant_id, true)){
                return $this->fail(200000);
            }
        }

        if(mb_strlen( str_replace( [Settings::get('default_user_name', '微信用户'), '微信用户', '普通用户'], '', UserUtils::get_cached_user_name($uid) )) != mb_strlen(UserUtils::get_cached_user_name($uid))){
            return $this->fail(200041);
        }

        $user = WxUser::find($uid);
        // 验证资料
        if(Settings::get('app_bureau_push_force_bind_phone', 0) == 1){
            if(_empty_($user->phone) && _empty_($__MINI_GLOBAL_CURRENT_PLAYER_ID__)){
                return $this->fail(200043, [
                    'title' => '未绑定手机号',
                    'content' => '前往绑定',
                    'confirmText' => '去绑定',
                    'target_type' => 6,
                    'target_id' => '/pagesA/mine/editmine/editmine?phone=1'
                ], '未绑定手机号');
            }
        }

        if(Settings::get('app_bureau_push_force_real_name', 0) == 1){
            if(_empty_($user->real_name) && _empty_($__MINI_GLOBAL_CURRENT_PLAYER_ID__)){
                return $this->fail(200043, [
                    'title' => '未实名认证',
                    'content' => '您还没有实名认证，是否前往认证',
                    'confirmText' => '去认证',
                    'target_type' => 6,
                    'target_id' => '/pagesA/mine/realname/realname'
                ], '未实名认证');
            }
        }

        if(Settings::get('app_bureau_push_force_subscribe_mp', 0) == 1){
            if(_empty_($user->weixin_mp_openid) && _empty_($__MINI_GLOBAL_CURRENT_PLAYER_ID__)){
                $weapp = new WeApp('mp');
                $mpServicer = $weapp->getMpServicer();
                try {
                    $url = $mpServicer->getQrCodeWithPara(0, 'user:bind:'.$user->id);
                }catch (\Exception $e){
                    return $this->fail(200006, [], '生成公众号二维码失败，请检查[全局配置-支付-微信-公众号]');
                }
                if($url){
                    $qrCode = QrCode::format('png')->size(300)->generate($url);
                    $image = Image::make($qrCode);
                    $image->resizeCanvas(300, 300 + 60, 'bottom', false, '#ffffff'); // 增加高度，保持宽高比，背景色为白色
                    $mp_app_name = Settings::get('mp_app_name', '');
                    $text_tip = '关注'.$mp_app_name.'公众号，可以更方便通知到您';
                    if(mb_strlen($mp_app_name) > 4){
                        $text_tip = '关注'.$mp_app_name.'公众号';
                    }
                    $image->text($text_tip, 150, 40, function($font){
                        $font->file(public_path('storage/font/DingTalk_JinBuTi_Regular.ttf')); // 字体文件路径
                        $font->size(13); // 字体大小
                        $font->color('#000000'); // 字体颜色
                        $font->align('center'); // 水平对齐
                        $font->valign('top'); // 垂直对齐
                    });
                    $base64 = 'data:image/png;base64,' . base64_encode($image->encode('png')->getEncoded());
                    return $this->fail(200043, [
                        'title' => '未关注公众号，无法实时获取通知',
                        'content' => '前往关注',
                        'confirmText' => '去关注',
                        'target_type' => 26,
                        'target_id' => $base64
                    ], '未关注公众号');
                }
            }
        }

        $now = Carbon::now();
        if(_empty_($the_id)){
            $the_id = 0;
            $the_base_time = $now;
        }else{
            $the_base_time = Carbon::createFromFormat('Y-m-d H:i:s', WxBureauGroup::where('bureau_id', $the_id)->orderBy('id', 'asc')->min('signup_start_time'));
            // 获取当前时间
            if ($now->lt($the_base_time)) {
                $the_base_time = $now;
            }
        }

        // 自定义验证规则
        $rules = [
            'bureau_type' => 'required|integer|in:1,2,3', // 假设 type 的枚举值为 1, 2, 3
            'title' => 'required|string',
            'intro' => 'required|string',
            'image_urls' => 'required|array',
            'image_urls.*' => 'string', // 确保每个图片 URL 是字符串
            'video_url' => 'nullable|string',
            'video_cover' => 'nullable|string',
            'tags' => 'nullable|array',
            'tags.*' => 'string|min:1', // 检查每一个 tag 是否为空
            'location.latitude' => 'required|numeric',
            'location.longitude' => 'required|numeric',
            'location.address_name' => 'required|string',
            'location.address_detailed' => 'required|string',
            'service_date_start' => 'required|date_format:Y-m-d',
            'service_date_end' => 'required|date_format:Y-m-d|after_or_equal:service_date_start', // 确保 service_date_end 大于 service_date_start
            'service_time_start' => 'required|date_format:H:i:s',
            'service_time_end' => 'required|date_format:H:i:s',
            'exposure_type' => 'required|integer|in:1,2,3',
            'refund_policy' => 'required|integer',
            'user_info_fill' => 'nullable|string',
            'group' => 'required|array',
            'group.*.id' => 'nullable|integer',
            'group.*.name' => 'nullable|string',
            'group.*.total_people' => 'required|integer',
            'group.*.cost_per_person' => 'required|numeric',
            'group.*.is_waiting' => 'required|boolean',
            'group.*.is_limit_one' => 'required|boolean',
            'group.*.is_real_name' => 'required|boolean',
            'group.*.signup_start_time' => 'nullable|date_format:Y-m-d H:i:s',
            'group.*.signup_end_time' => 'required|date_format:Y-m-d H:i:s|after_or_equal:group.*.signup_start_time', // signup_end_time 要大于等于 signup_start_time
            'group.*.signup_gender' => 'nullable|integer|in:0,1,2,3', // 假设 signup_gender 的枚举值为 1, 2,3
            'group.*.signup_scope' => 'nullable|integer|in:1,2' // 假设 signup_scope 的枚举值为 1, 2
        ];

        // 验证数据
        $validator = Validator::make($request->all(), $rules);

        // 如果验证失败，返回错误信息
        if ($validator->fails()) {
            $errors = $validator->errors();
            $first_error_message = $errors->first();
            if(strpos($first_error_message , 'location.address name') !== false){
                return $this->fail(200004, $errors, '请选择集合地点');
            } else if(strpos($first_error_message , 'The group.0.signup_end_time must be a date after or equal to group.0.signup_start_time') === 0){
                return $this->fail(200004, [], '报名截止时间应在报名开始时间之后');
            }else if(strpos($first_error_message , 'The group.0.signup_end_time ') === 0){
                return $this->fail(200004, [], '请填写报名截止时间');
            }
            return $this->fail(200004, $errors, $first_error_message);
        }

        $validatedData = $validator->validated();

        $file_state_change = [];

        // 处理 image_urls
        $image_urls = [];
        $content = '';
        if($validatedData['image_urls']){
            foreach ($validatedData['image_urls'] as $img_url){
                $img_info = ImageUtils::get_url_img_info($img_url);
                $obj = [
                    'url' => $img_url,
                    'width' => 0,
                    'height' => 0
                ];
                if($img_info){
                    $obj['width'] = $img_info['width'];
                    $obj['height'] = $img_info['height'];
                }
                $image_urls[] = $obj;
                $file_state_change[] = $img_url;
                $content .= '<img src="'.$img_url.'" style="width: 100%"/>';
            }
        }

        // 处理 video_url 和 video_cover
        if($validatedData['video_url'] && strpos($validatedData['video_url'], 'http') === 0){
            $file_state_change[] = $validatedData['video_url'];
            if($validatedData['video_cover'] && strpos($validatedData['video_cover'], 'http') === 0){
                $file_state_change[] = $validatedData['video_cover'];
            }else{
                $res = ImageUtils::upload_video_screenshot($validatedData['video_url']);
                if($res && $res['url']){
                    $validatedData['video_cover'] = $res['url'];
                    $file_state_change[] = $res['url'];
                }
            }
        }else{
            $validatedData['video_url'] = null;
            $validatedData['video_cover'] = null;
        }

        // 校验活动时间是否符合限制
        $serviceStartDateTime = Carbon::createFromFormat('Y-m-d H:i:s', $validatedData['service_date_start'] . ' ' . $validatedData['service_time_start']);
        $serviceEndDateTime = Carbon::createFromFormat('Y-m-d H:i:s', $validatedData['service_date_end'] . ' ' . $validatedData['service_time_end']);

        if ($serviceStartDateTime->lt($the_base_time->copy()->addMinutes(30))) {
            if($the_id > 0){
                return $this->fail(200004, [], '活动开始时间必须距离报名开始时间大于30分钟');
            }else{
                return $this->fail(200004, [], '活动开始时间必须距离当前时间大于30分钟');
            }
        }

        // 检查活动开始时间到结束时间是否小于30分钟
        if ($serviceEndDateTime->diffInMinutes($serviceStartDateTime) < 30) {
            return $this->fail(200004, [], '活动开始时间到结束时间必须大于30分钟');
        }

        // 校验报名时间是否符合限制
        foreach ($validatedData['group'] as $groupData) {
            $signup_start_time = isset($groupData['signup_start_time']) ? Carbon::createFromFormat('Y-m-d H:i:s', $groupData['signup_start_time']) : $the_base_time;
            $signup_end_time = Carbon::createFromFormat('Y-m-d H:i:s', $groupData['signup_end_time']);

            // 检查报名开始时间到结束时间是否小于30分钟
            if ($signup_end_time->diffInMinutes($signup_start_time) < 30) {
                return $this->fail(200004, [], '报名开始时间到结束时间必须大于30分钟');
            }

            // 检查报名截止时间到活动开始时间是否大于10天
            if ($signup_end_time->diffInDays($serviceStartDateTime) > 10) {
                return $this->fail(200004, [], '报名截止时间到活动开始时间不能超过10天');
            }

            if ($signup_end_time->lt($the_base_time->copy()->addMinutes(30))) {
                if($the_id > 0){
                    return $this->fail(200004, [], '报名截止时间应至少距离报名开始时间30分钟');
                }else{
                    return $this->fail(200004, [], '报名截止时间应至少距离当前时间30分钟');
                }
            }
        }


        // 如果是编辑模式下，原来的group还在不在
        if($the_id > 0){
            $curret_group_arr = WxBureauGroup::where('bureau_id', $the_id)->pluck('id')->toArray();
            $curret_group_arr_new = [];
            foreach ($validatedData['group'] as $groupData) {
                if(_array_key($groupData, 'id', 0) > 0){
                    $curret_group_arr_new[] = (int)$groupData['id'];
                }
            }

            foreach ($curret_group_arr as $group_id){
                if(!in_array($group_id, $curret_group_arr_new)){
                    return $this->fail(200004, [], '应该包含旧的组局的所有分组');
                }
            }
        }


        // 百度审核
        if(UserUtils::user_permissions_check_by_config($uid, 'audit_bureau_white_list')){
            $need_manual_review = false;
        }else{
            $need_manual_review = true;
            $is_audit_bureau = Settings::get('is_audit_bureau', 0);
            if ($is_audit_bureau == 2) {
                $filter_result = BaiduUtils::text_filter($validatedData['title']. ' ' . $validatedData['intro']);
                if($filter_result){
                    if($filter_result['hit_level'] == 2){
                        // 不合规
                        return $this->fail(200016, ['tip'=>$filter_result['tip_list'], 'hit_word'=>$filter_result['hit_word']]);
                    }else if($filter_result['hit_level'] == 0){
                        // 审核通过
                        $need_manual_review = false;
                    }
                }
            }else if($is_audit_bureau == 0){
                $need_manual_review = true;
            }else{
                $need_manual_review = false;
            }
        }
        // 0:审核中，1:审核通过
        $status = 1;
        if($need_manual_review){
            $status = 0;
        }

        // 生成MD5哈希
        $dataToHash = [
            'user_id' => $uid,
            'club_id' => $club_id,
            'bureau_type' => $validatedData['bureau_type'],
            'title' => $validatedData['title'],
            'intro' => $validatedData['intro'],
            'content' => $content,
            'image_urls' => json_encode($image_urls),
            'video_url' => $validatedData['video_url'],
            'video_cover' => $validatedData['video_cover'],
            'tags' => isset($validatedData['tags']) ? implode(',', $validatedData['tags']) : '',
            'service_date_start' => $validatedData['service_date_start'],
            'service_date_end' => $validatedData['service_date_end'],
            'service_time_start' => $validatedData['service_time_start'],
            'service_time_end' => $validatedData['service_time_end'],
            'longitude' => $validatedData['location']['longitude'],
            'latitude' => $validatedData['location']['latitude'],
            'address_name' => $validatedData['location']['address_name'],
            'address_detailed' => $validatedData['location']['address_detailed'],
            'refund_policy' => $validatedData['refund_policy'],
            'exposure_type' => $validatedData['exposure_type'],
            'user_info_fill' => $validatedData['user_info_fill'],
            'group' => []
        ];

        foreach ($validatedData['group'] as $groupData) {
            $dataToHash['group'][] = [
                'user_id' => $uid,
                'name' => $groupData['name'] ?? '',
                'club_id' => $club_id,
                'type' => $validatedData['bureau_type'],
                'total_people' => $groupData['total_people'],
                'cost_per_person' => $groupData['cost_per_person'],
                'is_waiting' => $groupData['is_waiting'],
                'is_limit_one' => $groupData['is_limit_one'],
                'is_real_name' => $groupData['is_real_name'],
                'signup_end_time' => isset($groupData['signup_end_time']) ? Carbon::createFromFormat('Y-m-d H:i:s', $groupData['signup_end_time']) : $serviceStartDateTime,
                'signup_scope' => $groupData['signup_scope'],
                'signup_gender' => $groupData['signup_gender']
            ];
        }

        $md5Hash = md5(json_encode($dataToHash));

        if(_empty_($the_id)){
            if(WxBureau::where('md5', $md5Hash)->exists()){
                return $this->fail(200010, [], '请勿重复发布');
            }
        }

        // 创建 Bureau 实例
        DB::beginTransaction();
        try {
            // todo:
            if($the_id > 0){
                $bureau = WxBureau::find($the_id);
            }else{
                $bureau = new WxBureau();
            }
            $bureau->user_id = $uid;
            $bureau->club_id = $club_id;
            $bureau->type = $validatedData['bureau_type'];
            $bureau->title = $validatedData['title'];
            $bureau->intro = $validatedData['intro'];
            $bureau->content = $content;
            $bureau->image_urls = json_encode($image_urls);
            $bureau->video_url = $validatedData['video_url'];
            $bureau->video_cover = $validatedData['video_cover'];
            $bureau->tags = isset($validatedData['tags']) ? implode(',', $validatedData['tags']) : '';
            $bureau->service_date_start = $validatedData['service_date_start'];
            $bureau->service_date_end = $validatedData['service_date_end'];
            $bureau->service_time_start = $validatedData['service_time_start'];
            $bureau->service_time_end = $validatedData['service_time_end'];
            $bureau->longitude = $validatedData['location']['longitude'];
            $bureau->latitude = $validatedData['location']['latitude'];
            $bureau->address_name = $validatedData['location']['address_name'];
            $bureau->address_detailed = $validatedData['location']['address_detailed'];
            $bureau->refund_policy = $validatedData['refund_policy'];
            $bureau->exposure_type = $validatedData['exposure_type'];
            if($the_id > 0){

            }else{
                $bureau->user_info_fill = $validatedData['user_info_fill'];
            }
            $bureau->ip = $__MINI_GLOBAL_IP__;
            $bureau->md5 = $md5Hash;
            $bureau->status = $status;
            $bureau->save();

            // 创建 BureauGroup 实例
            foreach ($validatedData['group'] as $groupData) {
                if($the_id > 0 && _array_key($groupData, 'id', 0) > 0){
                    $group = WxBureauGroup::find($groupData['id']);
                }else{
                    $group = new WxBureauGroup();
                }
                if(!_empty_($groupData['name'])){
                    $group->name = $groupData['name'];
                }
                $group->user_id = $bureau->user_id;
                $group->bureau_id = $bureau->id;
                $group->club_id = $bureau->club_id;
                $group->type = $validatedData['bureau_type'];
                $group->total_people = $groupData['total_people'];
                $group->cost_per_person = $groupData['cost_per_person'];
                $group->is_waiting = $groupData['is_waiting'];
                $group->is_limit_one = $groupData['is_limit_one'];
                $group->is_real_name = $groupData['is_real_name'];
                $group->signup_start_time = isset($groupData['signup_start_time']) ? Carbon::createFromFormat('Y-m-d H:i:s', $groupData['signup_start_time']) : current_time();
                $group->signup_end_time = isset($groupData['signup_end_time']) ? Carbon::createFromFormat('Y-m-d H:i:s', $groupData['signup_end_time']) : $serviceStartDateTime;
                $group->signup_scope = $groupData['signup_scope'] ?? 1; // 默认值为 1
                $group->signup_gender = $groupData['signup_gender'] ?? 0; // 默认值为 1
                $group->save();
            }

            Utils::image_state_change($file_state_change);

            if($bureau->type == 3){
                WxBureau::where('id', $bureau->id)->update([
                    'least_price' => WxBureauGroup::where('bureau_id', $bureau->id)->min('cost_per_team')
                ]);
            }else{
                WxBureau::where('id', $bureau->id)->update([
                    'least_price' => WxBureauGroup::where('bureau_id', $bureau->id)->min('cost_per_person')
                ]);
            }
            if($status === 0){
                UserUtils::assistant_notice_review(103, $bureau->id);
            }else{
                UserUtils::add_user_experience($uid, 17, 20);
            }

            DB::commit();
            return $this->success($bureau->id);
        } catch (\Exception $e) {
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
        }
        return $this->fail(200002, [], '服务器错误，请稍后再试');
    }
}
